package com.bw.lib_log.crash

import android.content.Context
import android.os.Looper
import java.io.File
import java.io.PrintWriter
import java.io.StringWriter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * @author ykj
 * @date 2025-10-16 15:59
 * @description
 */
//扩展函数
fun StringBuilder.aa(){
    append("aa")
}
class CrashHandler {
    //2222222:初始化，系统崩溃拦截换成自定义
    companion object{
        lateinit var context: Context
        fun init(context_: Context){
            context = context_
            //把系统默认的换成我的异常捕获，不能省略
            Thread.setDefaultUncaughtExceptionHandler(CrashHandlerProcessor)
        }
    }

    //111：自定义Thread.UncaughtExceptionHandler重写uncaughtException方法：把崩溃信息写到文件中
    object CrashHandlerProcessor:Thread.UncaughtExceptionHandler{
        private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        override fun uncaughtException(t: Thread, e: Throwable) {
            //1:构建完整的崩溃信息
            val msg = buildCrashReport(t,e)
            //2:保存崩溃信息
            saveToFile(msg.toString())
            // 3. 可选：继续系统默认处理（强制退出）
            defaultHandler?.uncaughtException(t, e)
        }
        //高阶函数
        inline  fun method(p:()->Unit){
            p()
        }
        private fun buildCrashReport(t: Thread, e: Throwable):StringBuilder {
//            val str = StringBuilder()
//            str.append("")
//            str.append("")
//            return str
            //apply配置节省代码：this 对象本身返回值
//            return StringBuilder().apply {
//                appendLine()
//                appendLine()
//                appendLine()
//            }
            //let:空对象调用:it lambda表达式最后一行作为返回值
//            val str:StringBuilder? = null
//            str?.append("")
//            str?.append("")
//            str?.aa()
//            str?.let {
//                it.appendLine("")
//                it.append("")
//                "hahah"   //作为返回结果
//            }
            //调用高阶函数
            method {
                println("")
            }


            return StringBuilder().apply {
                appendLine("\n>>>>>>>>>>>>>>>> Crash Report <<<<<<<<<<<<<<<<")
                appendLine("=== Crash Time ===")
                appendLine(getCurrentTime())

                appendLine("\n=== Device Info ===")
                appendLine("Brand: ${android.os.Build.BRAND}")
                appendLine("Model: ${android.os.Build.MODEL}")
                appendLine("Android SDK: ${android.os.Build.VERSION.SDK_INT}")
                appendLine("Fingerprint: ${android.os.Build.FINGERPRINT}")

                appendLine("\n=== App Info ===")
                appendLine("Version: ${getAppVersion()}")
                appendLine("Process ID: ${android.os.Process.myPid()}")

                appendLine("\n=== Thread Info ===")
                appendLine("Thread Name: ${t.name}")
                appendLine("Thread ID: ${t.id}")
                appendLine("Is Main Thread: ${t == Looper.getMainLooper().thread}")
                appendLine("\n=== Stack Trace ===")
                appendLine(getStackTraceString(e))
                appendLine("\n=== End of Report ===")
            }

        }

        private fun getCurrentTime(): String {
            return SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
                .format(Date())
        }

        private fun getAppVersion(): String? {
            return context.packageManager.getPackageInfo(context.packageName, 0).versionName
        }

        private fun getStackTraceString(throwable: Throwable): String {
            val sw = StringWriter()
            val pw = PrintWriter(sw)
            throwable.printStackTrace(pw)
            pw.flush()
            return sw.toString()
        }
        private val FILE_NAME_FORMAT = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
        private fun saveToFile(content: String) {
            try {
                val dir = context.getDir("crash",Context.MODE_PRIVATE)
                val crashFile = File(dir, "crash_${FILE_NAME_FORMAT.format(Date())}.txt")
                crashFile.writeText(content)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }



    }
}